package cn.swust.designpatternlearningplatform.service.impl;

import cn.swust.designpatternlearningplatform.common.exception.CustomException;
import cn.swust.designpatternlearningplatform.common.utils.PdfGenerateUtil;
import cn.swust.designpatternlearningplatform.dao.TestPaperExportDao;
import cn.swust.designpatternlearningplatform.domain.bo.FileBo;
import cn.swust.designpatternlearningplatform.domain.dto.*;
import cn.swust.designpatternlearningplatform.domain.entity.TestPaperTopicContent;
import cn.swust.designpatternlearningplatform.domain.vo.StudentProblemSolvingSituationVo;
import cn.swust.designpatternlearningplatform.service.TestPaperExportService;
import cn.swust.designpatternlearningplatform.service.TopicService;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class TestPaperExportServiceImpl implements TestPaperExportService {

    private final PdfGenerateUtil pdfGenerateUtil;

    private final TestPaperExportDao testPaperExportDao;

    private final TopicService topicService;

    /**
     * 下载某试卷下对应的学生做题情况（将学生的做题记录连同试卷一并导出）
     *
     * @param situationVo 用户选择的参数
     * @param response
     * @return org.springframework.http.ResponseEntity<java.lang.Byte>
     * @author Tang
     * @date 2023/10/15 1:02
     **/
    @Override
    public void exportTestPaperEachStudent(StudentProblemSolvingSituationVo situationVo, HttpServletResponse response) {
        if (situationVo.getPaperNumber() == null || situationVo.getPaperNumber().isEmpty()) {
            throw new CustomException("试卷编号不能为空");
        }
        if (situationVo.getClassNumberList() == null || situationVo.getClassNumberList().isEmpty()) {
            throw new CustomException("必须选择班级");
        }
        //获取试卷信息
        TestPaperTopicContent testPaperTopicContent = testPaperExportDao.selectTestPaperTopicContent(situationVo.getPaperNumber());
        if (testPaperTopicContent == null) {
            throw new CustomException("选择的试卷不存在");
        }
        //查询具体的题目信息
        List<TopicDto> topicByTopicIds = topicService.getTopicByTopicIds(testPaperTopicContent.getTopicIdList());
        //封装模板渲染需要的试卷信息
        TestPaperTopicContentDto testPaperTopicContentDto = new TestPaperTopicContentDto();
        BeanUtils.copyProperties(testPaperTopicContent, testPaperTopicContentDto);
        testPaperTopicContentDto.setTopicDtoList(topicByTopicIds);
        //获取学生的做题信息
        List<StudentProblemSolvingSituationDto> problemSolvingSituations = testPaperExportDao
                .selectStudentTestSituation(situationVo.getPaperNumber(), situationVo.getClassNumberList());
        //导出学生做题信息
        exportTestZip(testPaperTopicContentDto, problemSolvingSituations, response);
    }

    private PaperExportDto convert2PaperExportDto(TestPaperTopicContentDto contentDto, StudentProblemSolvingSituationDto situationDto) {
        PaperExportDto paperExportDto = new PaperExportDto();
        //试卷总分
        paperExportDto.setTotalScore(contentDto.getTotalScore());
        //试卷名字
        paperExportDto.setPaperName(contentDto.getTestName());
        //试卷题目信息
        paperExportDto.setTopicDtoList(contentDto.getTopicDtoList());
        //学生信息
        paperExportDto.setStudentDto(situationDto.getStudentDto());
        //学生自己的做题信息
        paperExportDto.setSelfRecord(situationDto.getRecordList());
        //学生自己的得分
        paperExportDto.setScore(situationDto.getScore());
        return paperExportDto;
    }

    public TestPaperExportServiceImpl(PdfGenerateUtil pdfGenerateUtil, TestPaperExportDao testPaperExportDao, TopicService topicService) {
        this.pdfGenerateUtil = pdfGenerateUtil;
        this.testPaperExportDao = testPaperExportDao;
        this.topicService = topicService;
    }

    /**
     * 批量导出试卷结果
     *
     * @param contentDto
     * @param situationDtos
     * @param response
     * @return void
     * @author Tang
     * @date 2023/10/17 10:39
     **/
    private void exportTestZip(TestPaperTopicContentDto contentDto, List<StudentProblemSolvingSituationDto> situationDtos, HttpServletResponse response) {
        List<PaperExportDto> exportDtoList = new ArrayList<>(situationDtos.size());
        //生成试卷结果列表
        situationDtos.forEach(situationDto -> {
            exportDtoList.add(convert2PaperExportDto(contentDto, situationDto));
        });
        //生成试卷pdf文件
        List<FileDto> fileDtos = generatePdf(exportDtoList);
        try {
            response.reset();
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("导出结果.zip", "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.error("编码不支持,{}", e.getMessage());
            throw new CustomException("请联系后台人员解决");
        }

        try (ServletOutputStream servletOutputStream = response.getOutputStream()) {
            pdfGenerateUtil.zipFile(servletOutputStream, fileDtos);
        } catch (IOException e) {
            throw new CustomException("下载失败");
        }
    }

    /**
     * 转换FileBoList对象
     *
     * @param paperExportDto
     * @return java.util.List<cn.swust.designpatternlearningplatform.domain.bo.FileBo>
     * @author Tang
     * @date 2023/10/17 11:23
     **/
    private List<FileBo> convert2FileBo(List<PaperExportDto> paperExportDto) {
        List<FileBo> fileBoList = new ArrayList<>(paperExportDto.size());
        for (PaperExportDto exportDto : paperExportDto) {
            FileBo fileBo = new FileBo();
            StudentDto studentDto = exportDto.getStudentDto();
            if (studentDto == null) {
                continue;
            }
            fileBo.setFileName(studentDto.getStudentName() + "-" + studentDto.getStudentNumber() + "-" + exportDto.getPaperName());
            fileBo.setFileParentFolder(studentDto.getClassNumber());
            Map<String, Object> properties = new HashMap<>();
            properties.put("paperExportDto", exportDto);
            fileBo.setProperties(properties);
            fileBoList.add(fileBo);
        }
        return fileBoList;
    }

    /**
     * 可异步
     *
     * @param paperExportDto
     * @return void
     * @author Tang
     * @date 2023/10/17 10:40
     **/
    protected List<FileDto> generatePdf(List<PaperExportDto> paperExportDto) {
        try {
            List<FileBo> fileBoList = convert2FileBo(paperExportDto);
            return pdfGenerateUtil.generatePdf(fileBoList, "TestExport.ftl");
        } catch (TemplateException | IOException e) {
            throw new CustomException("请联系后台人员解决");
        }
    }

}
